#! /usr/bin/python

# Copyright (C) 2012 Zhan Zongru
# Author: Zhan Zongru
# Contact: zhan.zr@gmail.com
# License: New BSD License

import webbrowser, subprocess, datetime, os
import threading
import xml.dom.minidom
import random
import ctypes
import sys

class Question:
	"""Question Class.
    """
	def __init__(self, title, descript, id=0):
		self.title = title
		self.descript = descript
		self.id=id
		
class IssueQuestion(Question):
	"""Issue Question Class.
    """
	def __init__(self, title, descript, id):
		super(IssueQuestion, self).__init__(title, descript, id)

class ArgueQuestion(Question):
	"""Argue Question Class.
    """
	def __init__(self, title, descript, id):
		super(ArgueQuestion, self).__init__(title, descript, id)		
		
class Gre_aw:
	"""GRE Analystic Writting Test Class.
	"""
	def __init__(self, root):
		self.root = root
		self.i_sec = 30*60
		self.a_sec = 30*60
		self.sect_name='Issue'
		self.quest_dict={'null':0}
		
	def build_ui(self):
		"""Build the UI of the analystic writing.
		"""
		#Top Frame 
		top_frame = tkinter.Frame(self.root)
		top_frame.pack(side=tkinter.TOP)
		
		#Top Log Frame
		top_logo_frame = tkinter.Frame(top_frame)
		top_logo_frame.pack(side=tkinter.LEFT)

		logo_lab = tkinter.Label(top_logo_frame, text='Logo',justify=tkinter.LEFT, font=("Arial", 18))

		logo_lab.pack(side=tkinter.LEFT)
		self.start_btn = tkinter.Button(top_logo_frame, text='Start', command=self.start_sect)
		self.start_btn.pack(side=tkinter.LEFT)
		#Create a timer, when the start button pushed, the timer starts
		self.issue_timer = RepeatTimer.repeat_timer(1.0, self.update_timer, self.i_sec+30)
		self.argue_timer = RepeatTimer.repeat_timer(1.0, self.update_timer, self.i_sec+30)

		#Top Title Frame
		top_title_frame = tkinter.Frame(top_frame)
		top_title_frame.pack(side=tkinter.LEFT)
		self.title_lab = tkinter.Label(top_title_frame, fg="blue", text=self.sect_name, width=35, wraplength=520,justify=tkinter.CENTER, font=("Arial", 18))
		self.title_lab.pack(side=tkinter.LEFT)
		
		#Top Function Frame
		top_func_frame = tkinter.Frame(top_frame)
		top_func_frame.pack(side=tkinter.RIGHT)
		
		top_func_up_frame = tkinter.Frame(top_func_frame)
		top_func_up_frame.pack(side=tkinter.TOP)
		q_s_btn = tkinter.Button(top_func_up_frame, text='Quit/Save', command=self.quit_save)
		exit_btn = tkinter.Button(top_func_up_frame, text='Exit Sect', command=self.exit_sect)
		help_btn = tkinter.Button(top_func_up_frame, text='Help', command=self.help_sect)
		next_btn = tkinter.Button(top_func_up_frame, text='Next', command=self.next_sect)
		next_btn.pack(side=tkinter.RIGHT)
		help_btn.pack(side=tkinter.RIGHT)
		exit_btn.pack(side=tkinter.RIGHT)
		q_s_btn.pack(side=tkinter.RIGHT)
		
		top_func_time_frame = tkinter.Frame(top_func_frame)
		top_func_time_frame.pack(side=tkinter.TOP)
		self.hidetime_btn = tkinter.Button(top_func_time_frame, text='Hide Time', command=self.hide_time)
		self.time_tick_lab = tkinter.Label(top_func_time_frame, text='30:00:00', width=10, wraplength=100,justify=tkinter.LEFT, font=("Arial", 14))
		self.time_tick_lab.pack(side=tkinter.RIGHT)
		self.hidetime_btn.pack(side=tkinter.RIGHT)
		self.hidetime=False
		
		# Bottom Frame
		btn_frame = tkinter.Frame(self.root)
		btn_frame.pack(side=tkinter.BOTTOM)
		
		# Bottom Left frame(Question)
		left_frame = tkinter.Frame(btn_frame)
		left_frame.pack(side=tkinter.LEFT)
		right_frame = tkinter.Frame(btn_frame)
		right_frame.pack(side=tkinter.RIGHT)

		# Choose a random issue question
		Arr = self.read_issue()
		leng = len(Arr)
		r_id = random.randrange(0,leng)
		self.quest_dict[self.sect_name]=Arr[r_id]
		
		self.question_id_lab = tkinter.Label(left_frame, justify=tkinter.LEFT, text=self.sect_name+' Question '+ str(r_id), width=50, wraplength=520, font=("Helvetica", 12))
		self.question_id_lab.pack(side=tkinter.TOP)

		self.question_t_lab = tkinter.Label(left_frame, justify=tkinter.LEFT, text=Arr[r_id].title, width=50, wraplength=520, font=("Helvetica", 12), fg=self.question_id_lab.cget('background'))
		self.question_t_lab.pack(side=tkinter.TOP)
		
		self.question_hr_lab = tkinter.Label(left_frame, justify=tkinter.LEFT, text='-'*self.question_t_lab.cget('width'), width=50, wraplength=520, font=("Helvetica", 12), fg=self.question_id_lab.cget('background'))
		self.question_hr_lab.pack(side=tkinter.TOP)
		
		self.question_d_lab = tkinter.Label(left_frame, justify=tkinter.LEFT, text=Arr[r_id].descript, width=50, wraplength=520, font=("Palatino Linotype", 10), fg=self.question_id_lab.cget('background'))
		self.question_d_lab.pack(side=tkinter.TOP)
		
		#Bottom Right Frame(editor button and text entry)
		self.answer_text = tkinter.Text(right_frame, font=("Arial", 14), width=80, undo=1)
		editor_frame = tkinter.Frame(right_frame)
		self.cut_btn = tkinter.Button(editor_frame, text='Cut', command=self.editor_cut)
		self.paste_btn = tkinter.Button(editor_frame, text='Paste',state=tkinter.DISABLED, command=self.editor_paste)
		# cut_flag,True : Cut button available, False : Cut button unavailable , paste button  state is inversion of the cut button
		self.selected = ""
		self.cut_flag = True
		
		self.undo_btn = tkinter.Button(editor_frame, text='Undo', command=self.editor_undo)
		self.redo_btn = tkinter.Button(editor_frame, text='Redo', command=self.editor_redo)
		self.cut_btn.pack(side=tkinter.LEFT)
		self.paste_btn.pack(side=tkinter.LEFT)
		self.undo_btn.pack(side=tkinter.LEFT)
		self.redo_btn.pack(side=tkinter.LEFT)
		
		editor_frame.pack(side=tkinter.TOP)
		self.answer_text.pack(side=tkinter.TOP)
#		Selection event bind, TODO
#		self.answer_text.tag_bind('important', '<Selection>', misc.dummy)
		
		return self.root
		
	def save_answer(self, sect_name, question):
		a_text = self.answer_text.get(1.0, tkinter.END)
		a_file_name=''
		wc_about = a_text.strip().count(' ')+1
		if wc_about < 150 :
			tkinter.messagebox.showinfo(title='Too Laconic!', message='Your response is just about '+str(wc_about) + ' words, worth little to save!')
			return a_file_name
					
		time_now=datetime.datetime.now()
			
		a_file_name=str(question.id)+'_'+g_username+datetime.datetime.now().strftime("%Y%m%d_%H%M%S")+'_'+'.txt'
				
		a_file=open(os.path.join(os.getcwd(),'answer_'+self.sect_name.lower(),a_file_name),mode='w')
		a_file.write(question.title)
		a_file.write('-'*10)
		a_file.write('\r\n')
		a_file.write(a_text)
		a_file.close()	
		return a_file_name
				
	def read_issue(self):
		i_doc = xml.dom.minidom.parse(os.path.join(os.getcwd(),"issue.xml"))

		i_nodes=i_doc.getElementsByTagName('subject')
		IssueArr=[]
		for i_node in i_nodes:
			id = int(i_node.getAttribute('id'))
			Tstr=""
			Dstr=""
			i_nodes_T = i_node.getElementsByTagName('Title')
			for i_node_T in i_nodes_T:
				for i_node_Tc in i_node_T.childNodes:
		#			print(i_node_Tc.data)
					Tstr=i_node_Tc.data

			i_nodes_D = i_node.getElementsByTagName('Descript')
			for i_node_D in i_nodes_D:
				for i_node_Dc in i_node_D.childNodes:
		#			print(i_node_Dc.data)
					Dstr=i_node_Dc.data
					
			IssueArr.append(IssueQuestion(Tstr,Dstr,id))

		return IssueArr
		
	def read_argue(self):
		a_doc = xml.dom.minidom.parse(os.path.join(os.getcwd(),"argue.xml"))

		a_nodes=a_doc.getElementsByTagName('subject')
		ArgueArr=[]
		for a_node in a_nodes:
			id = int(a_node.getAttribute('id'))
			Tstr=""
			Dstr=""
			a_nodes_T = a_node.getElementsByTagName('Title')
			for a_node_T in a_nodes_T:
				for a_node_Tc in a_node_T.childNodes:
					Tstr=a_node_Tc.data

			a_nodes_D = a_node.getElementsByTagName('Descript')
			for a_node_D in a_nodes_D:
				for a_node_Dc in a_node_D.childNodes:
					Dstr=a_node_Dc.data
						
			ArgueArr.append(ArgueQuestion(Tstr,Dstr,id))

		return ArgueArr
		
	def quit_save(self):
		"""Save the Answer and quit.
		"""
		
		response = tkinter.messagebox.askokcancel(title='Warning', message='Do you want to quit and save the answer')
			
		# Save and quit
		if True==response:
			a_file_name = self.save_answer(self.sect_name, self.quest_dict[self.sect_name])
			
			a_path = os.path.join(os.getcwd(),'answer_'+self.sect_name.lower(),a_file_name)

			if os.path.isfile(a_path):
				# open the answer
				os.system(a_path)
						
			# Next sect
			self.next_sect()
		else:
			pass
			
	def exit_sect(self):
		self.issue_timer.cancel()
		self.argue_timer.cancel()
		try:
			self.root.destroy()
		except tkinter.TclError: 
			pass

	def help_sect(self):
		webbrowser.open_new_tab('help.html')

	def next_sect(self):
		"""Move to the next test section.
		"""
#		print(self.sect_name+" next_sect")
		if "Issue"==self.sect_name:
			#Decorate the Issue UI
			self.issue_timer.cancel()
			
			self.sect_name='Argue'
			
			self.title_lab.config(text=self.sect_name)
			self.start_btn.config(state=tkinter.NORMAL)
			self.answer_text.delete(1.0, tkinter.END)
		
			self.question_t_lab.config(fg=self.question_id_lab.cget('bg'))
			self.question_hr_lab.config(fg=self.question_id_lab.cget('bg'))
			self.question_d_lab.config(fg=self.question_id_lab.cget('bg'))
			
			self.time_tick_lab.config(text="00:00:00")
			
			# Choose a random argue question
			Arr = self.read_argue()
			leng = len(Arr)
			r_id = random.randrange(0,leng)
			self.quest_dict[self.sect_name]=Arr[r_id]
			
			self.question_id_lab.config(text=self.sect_name+' Question '+ str(Arr[r_id].id))
			self.question_t_lab.config(text=Arr[r_id].title)
			self.question_d_lab.config(text=Arr[r_id].descript)
			
			return
		else:
			self.exit_sect()
			return
			
	def start_sect(self):
		if 'Issue'==self.sect_name:
			self.question_t_lab.config(fg=self.question_id_lab.cget('fg'))
			self.question_hr_lab.config(fg=self.question_id_lab.cget('fg'))
			self.question_d_lab.config(fg=self.question_id_lab.cget('fg'))
			self.start_btn.config(state=tkinter.DISABLED)
			
			self.issue_start=datetime.datetime.now()
			self.issue_timer.start()	
		elif 'Argue'==self.sect_name:
			self.question_t_lab.config(fg=self.question_id_lab.cget('fg'))
			self.question_hr_lab.config(fg=self.question_id_lab.cget('fg'))
			self.question_d_lab.config(fg=self.question_id_lab.cget('fg'))
			self.start_btn.config(state=tkinter.DISABLED)
			
			self.argue_start=datetime.datetime.now()
			self.argue_timer.start()
		else:
			pass
			
	def update_timer(self):
		if 'Issue'==self.sect_name:
			delta_time = datetime.datetime.now() - self.issue_start
			remaining_sec = self.i_sec - delta_time.seconds
			
			if remaining_sec <=0 :
				self.time_tick_lab.config(text="00:00:00")
				
				#save the answer text
				a_file_name = self.save_answer(self.sect_name, self.quest_dict[self.sect_name])
				
				response = tkinter.messagebox.askokcancel(title='Time Exhausted!', message='Time exhausted, answer saved as '+ os.path.join(os.getcwd(),'answer_'+self.sect_name.lower(),a_file_name) +' Yes to Exit, No to Continue write!')
					
				if True == response:
					# open the answer
					os.system(os.path.join(os.getcwd(),'answer_'+self.sect_name.lower(),a_file_name))
					# Next Section
					self.next_sect()
				else:
					pass
			else:
				# Update the issue time display
				time_str=str("%02d:%02d:%02d" % (remaining_sec/(60*60), (remaining_sec/60)%60, remaining_sec%60))
				self.time_tick_lab.config(text=time_str)
		elif 'Argue'==self.sect_name:
			delta_time = datetime.datetime.now() - self.argue_start
			remaining_sec = self.a_sec - delta_time.seconds
			
			if remaining_sec <=0 :
				self.time_tick_lab.config(text="00:00:00")
				
				#save the answer text
				a_file_name = self.save_answer(self.sect_name, self.quest_dict[self.sect_name])
				
				response = tkinter.messagebox.askyesno(title='Time Exhausted!', message='Time exhausted, answer saved as '+ os.path.join(os.getcwd(),'answer_'+self.sect_name.lower(),a_file_name)+' Yes to Exit, No to Continue write!')
					
				if True == response:
					# open the answer
					os.system(os.path.join(os.getcwd(),'answer_'+self.sect_name.lower(),a_file_name))
					# Next Section
					self.next_sect()
				else:
					pass
			else:
				# Update the argue time display
				time_str=str("%02d:%02d:%02d" % (remaining_sec/(60*60), (remaining_sec/60)%60, remaining_sec%60))
				self.time_tick_lab.config(text=time_str)
		else:
			pass
		
	def hide_time(self):
		if self.hidetime:
			self.time_tick_lab.config(fg=self.question_id_lab.cget('fg'))
			self.hidetime = False
			self.hidetime_btn.config(text='Hide Time')
		else:
			self.time_tick_lab.config(fg=self.question_id_lab.cget('bg'))
			self.hidetime = True
			self.hidetime_btn.config(text='Disp Time')

	def editor_cut(self):
		"""
		"""
		try:
			self.selected = self.answer_text.selection_get()
			self.cut_flag = False
			self.paste_btn.config(state=tkinter.NORMAL)
			self.cut_btn.config(state=tkinter.DISABLED)
			self.answer_text.delete(tkinter.SEL_FIRST,tkinter.SEL_LAST)
		except tkinter.TclError: 
			pass
			
	def editor_paste(self):
		"""insert the selected text into the cursor
		"""
		self.answer_text.insert(tkinter.INSERT, self.selected)
		self.cut_flag = True
		self.paste_btn.config(state=tkinter.DISABLED)
		self.cut_btn.config(state=tkinter.NORMAL)
		
	def editor_undo(self):
		print('editor_undo')	
		
	def editor_redo(self):
		print('editor_redo')		

if __name__ == '__main__':
	if '2' == sys.version[0]:
		os.system('python gawprepare_py2.py')
	else:
		sys.path.append(os.getcwd())
		import urllib.request
		import tkinter, tkinter.messagebox, tkinter.font
		import RepeatTimer
		import misc
		
		g_username = os.getlogin()
		
		# Create a root Tk
		root_tk = tkinter.Tk()
		
		aw_test = Gre_aw(root_tk)
		aw_test.build_ui()
		
		# Main Loop
		root_tk.config(width=root_tk.maxsize()[0], height=root_tk.maxsize()[1])
		root_tk.mainloop()
	
